`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////Asyncsys Lab////////////////////////////////////////
// Author: Zhenbang Kang
// Email: kangzhb20@lzu.edu.cn
// Create Date: 2022/06/10 
// Module Name: click_control_first
// Project Name: ac8051 (Asynchronous Click 8051)
// Target Devices: XC7A100TFGG484-2
// Tool Versions: Vivado 2019.1
// Description:IF&ID ADL
// Revision: V2.0
//////////////////////////////////////////////////////////////////////////////////

module click_control_first(               
						rst_n,
						in_R,                   //from  click_start 
						in_R_rst,
//						in_A,                   //to    click_start 
						in_R_icache,            //from  icache
						in_A_icache_click2,     //from  icache            
						in_A_icache,            //to    icacahe
						out_R_delay_final2,     //to    icache
//						in_A_ex,                //from  id/ex
//						out_R_delay_final4,     //to    id/ex
						fire_cyc,
						fire_out,
						fire_end_second,
						in_R_second,
						fire_second,
						o_second_begin,
						fire_rx_end
    );
               input    rst_n;
               input    in_R;                   //from  click_start
               input    in_R_rst; 
//               output   in_A;                   //to    click_start 
               input    in_R_icache;            //from  icache
               input    in_A_icache_click2;     //from  icache            
               output   in_A_icache;            //to    icacahe
               output   out_R_delay_final2;     //to    icache
//               input    in_A_ex;                //from  id/ex
//               output   out_R_delay_final4;     //to    id/ex
               output   fire_cyc;
               output   fire_out;
               input    fire_end_second;
               output   in_R_second;
               output   fire_second;
               output   o_second_begin;
                input   fire_rx_end;

wire    fire_end_second;
wire    in_R_rst;
wire    rst_n;
(* dont_touch = "true" *)wire    in_R;                   //from  click_start 
//(* dont_touch = "true" *)  wire    in_A;                   //to    click_start 
(* dont_touch = "true" *)wire    in_R_icache;            //from  icache
(* dont_touch = "true" *)wire    in_A_icache_click2;     //from  icache            
(* dont_touch = "true" *)wire    in_A_icache;            //to    icacahe
(* dont_touch = "true" *)reg    out_R_delay_final2;     //to    icache
wire    out_R_delay_newfinal2;
//(* dont_touch = "true" *)wire    in_A_ex;                //from  id/ex
(* dont_touch = "true" *)wire    out_R_delay_final4;     //to    id/ex
wire    fire_out;

(* dont_touch = "true" *)wire    in_A1;
(* dont_touch = "true" *)wire    in_A2;
(* dont_touch = "true" *)wire    in_A3;
(* dont_touch = "true" *)wire    in_A4;
(* dont_touch = "true" *)wire    in_A_delay2;
(* dont_touch = "true" *)wire    in_A_delay4;
(* dont_touch = "true" *)wire    in_A_delay6;
(* dont_touch = "true" *)wire    in_A_delay8;
(* dont_touch = "true" *)wire    out_R1;
(* dont_touch = "true" *)wire    out_R2;
(* dont_touch = "true" *)wire    out_R3;
(* dont_touch = "true" *)wire    out_R4;
(* dont_touch = "true" *)wire    out_R_delay1;
(* dont_touch = "true" *)wire    out_R_delay3;
(* dont_touch = "true" *)wire    out_R_delay5;
(* dont_touch = "true" *)wire    out_R_delay7;
(* dont_touch = "true" *)wire    out_R_delay_final1;
(* dont_touch = "true" *)wire    out_R_delay_final3;
reg out_A_delay_final4;
(* dont_touch = "true" *)wire    out_A1;
(* dont_touch = "true" *)wire    out_A2;
(* dont_touch = "true" *)wire    out_A3;
(* dont_touch = "true" *)wire    out_A4;
(* dont_touch = "true" *)wire    out_A_delay1;
(* dont_touch = "true" *)wire    out_A_delay2;
wire    fire1;
wire    fire2;
wire    fire3;
wire    fire4;
wire    fire_cyc1;
wire    fire_cyc2;
wire    fire_cyc3;
wire    fire_cyc4;
wire    fire_cyc;
(* dont_touch = "true" *)wire    out_R_clickd1;
(* dont_touch = "true" *)wire    out_R_clickd2;
(* dont_touch = "true" *)wire    out_R_clickd3;
(* dont_touch = "true" *)wire    out_R_clickd4;

(* dont_touch = "true" *)wire    in_A_clickd1;
(* dont_touch = "true" *)wire    in_A_clickd2;
(* dont_touch = "true" *)wire    in_A_clickd3;
(* dont_touch = "true" *)wire    in_A_clickd4;   

wire    fire_begin;
wire    inv_fire_begin; 
wire    first_end;
wire    inv_first_end;
wire    fire_second;
(*dont_touch="true"*)wire    out_R_end1;
(*dont_touch="true"*)reg     out_A_end1;
(*dont_touch="true"*)reg     second_begin;
(*dont_touch="true"*)wire    o_second_begin;
    
(*dont_touch="true"*)reg     out_R_second;
(*dont_touch="true"*)reg     state;
(*dont_touch="true"*)wire    in_R_second;
 wire fire_rx_end;
// reg    in_R3;
 wire   fire_delay4; 
 wire   inv_fire_delay4;
 reg    out_A_delay4;
 wire   fire_click3;
(* keep_hierarchy = "yes" *)click click_1(  .in_R(in_R),      .in_A(),    .out_R(out_R1),   .out_A(out_R_delay_final1),   .fire(fire1));
    /***************************************************delay_unit_1***************************************************/
(* keep_hierarchy = "yes" *)click click_delay1(  .in_R(out_R1),   .in_A(),   .out_R(out_R_delay1),   .out_A(in_A_clickd1),   .fire());
(* keep_hierarchy = "yes" *)delay_unit delay_1(  .in_R(out_R_delay1),   .in_A(in_A_clickd1),  .out_R(out_R_clickd1),   .out_A(in_A_delay2),   .fire(fire_cyc1));
(* keep_hierarchy = "yes" *)click click_delay2(  .in_R(out_R_clickd1),   .in_A(in_A_delay2),   .out_R(out_R_delay_final1),   .out_A(in_A2),   .fire());
    /****************************************************************************************************************/   
(* keep_hierarchy = "yes" *)click click_2(  .in_R(out_R_delay_final1),    .in_A(in_A2),    .out_R(out_R2),   .out_A(out_R_delay_newfinal2),   .fire(fire2));
    /***************************************************delay_unit_2***************************************************/
(* keep_hierarchy = "yes" *)click click_delay3(  .in_R(out_R2),   .in_A(),   .out_R(out_R_delay3),   .out_A(in_A_clickd2),   .fire());
(* keep_hierarchy = "yes" *)delay_unit delay_2(  .in_R(out_R_delay3),   .in_A(in_A_clickd2),  .out_R(out_R_clickd2),   .out_A(in_A_delay4),   .fire(fire_cyc2));
(* keep_hierarchy = "yes" *)click click_delay4(  .in_R(out_R_clickd2),   .in_A(in_A_delay4),   .out_R(out_R_delay_newfinal2),   .out_A(out_A_delay4),   .fire(fire_delay4));
 /***********************************************************************************************************************/
assign inv_fire_delay4 = ~fire_delay4;
always@(posedge inv_fire_delay4 or negedge in_R_rst)begin
    if(!in_R_rst)begin
        out_A_delay4 <= 'b0;
    end else begin
        out_A_delay4 <= out_R_delay_newfinal2;
    end
end

assign fire_click3 = (second_begin==1'b0)?out_R_delay_newfinal2:fire_rx_end;

 always@(posedge fire_click3 or negedge rst_n)begin
    if(!rst_n)begin
        out_R_delay_final2 <= 'b0;
    end else begin
        out_R_delay_final2 <= ~out_R_delay_final2;
    end
end
 
    
    /****************************************************************************************************************/
(* keep_hierarchy = "yes" *)click click_3(  .in_R(out_R_delay_final2),    .in_A(),    .out_R(out_R3),   .out_A(out_R_delay_final3),   .fire(fire3));
    /***************************************************delay_unit_3***************************************************/
(* keep_hierarchy = "yes" *)click click_delay5(  .in_R(out_R3),   .in_A(),   .out_R(out_R_delay5),   .out_A(in_A_clickd3),   .fire());
(* keep_hierarchy = "yes" *)delay_unit delay_3(  .in_R(out_R_delay5),   .in_A(in_A_clickd3),  .out_R(out_R_clickd3),   .out_A(in_A_delay6),   .fire(fire_cyc3));
(* keep_hierarchy = "yes" *)click click_delay6(  .in_R(out_R_clickd3),   .in_A(in_A_delay6),   .out_R(out_R_delay_final3),   .out_A(in_A_icache),   .fire());
    
    
    /****************************************************************************************************************/
(* keep_hierarchy = "yes" *)click click_4(  .in_R(in_R_icache),    .in_A(in_A_icache),    .out_R(out_R4),   .out_A(out_R_delay_final4),   .fire(fire4));
     /***************************************************delay_unit_4***************************************************/
(* keep_hierarchy = "yes" *)click click_delay7(  .in_R(out_R4),   .in_A(),   .out_R(out_R_delay7),   .out_A(in_A_clickd4),   .fire());
(* keep_hierarchy = "yes" *)delay_unit delay_4(  .in_R(out_R_delay7),   .in_A(in_A_clickd4),  .out_R(out_R_clickd4),   .out_A(in_A_delay8),   .fire(fire_cyc4));
(* keep_hierarchy = "yes" *)click click_delay8(  .in_R(out_R_clickd4),   .in_A(in_A_delay8),   .out_R(out_R_delay_final4),   .out_A(out_A_delay_final4),   .fire(fire_begin));
    /****************************************************************************************************************/
  assign inv_fire_begin = ~fire_begin;
  always@(posedge inv_fire_begin or negedge in_R_rst)begin
        if(!in_R_rst)begin
            out_A_delay_final4 <= 'b0;
        end else begin
            out_A_delay_final4 <= out_R_delay_final4;
        end
  end
  
    
  always@(posedge fire_begin or negedge rst_n)begin
        if(!rst_n)begin
            second_begin <= 'b0;
        end else begin
            second_begin <= 'b1;
        end
  end  
 assign o_second_begin = second_begin;
   (* keep_hierarchy = "yes" *) click  click_end1( .in_R(second_begin), .in_A(), .out_R(out_R_end1), .out_A(out_A_end1), .fire(first_end));
   assign inv_first_end = ~first_end;   
   always@(posedge inv_first_end or negedge in_R_rst)begin
        if(!in_R_rst)begin
            out_A_end1 <= 'b0;
        end else begin
            out_A_end1 <= out_R_end1;
        end
   end
   
  assign fire_second = first_end | fire_end_second; 
  
  always@(posedge fire_second or negedge rst_n)begin
        if(!rst_n)begin
            out_R_second <= 'b0;
            state <= 'b0;
        end else if(state == 1'b0)begin
            out_R_second <= ~out_R_second;
        end else if(state == 1'b1)begin
            out_R_second <= out_R_delay_final4;
        end else begin
            out_R_second <= out_R_second;
            state <= 'b1;
        end
  end   
    assign in_R_second = out_R_second;
    assign fire_out=fire1|fire2|fire3|fire4;
    assign fire_cyc=fire_cyc1|fire_cyc2|fire_cyc3|fire_cyc4;
endmodule
